package MyThread_demo.StampedLock_demo;

import java.util.concurrent.locks.StampedLock;

/**
 * @author ChenYongHao
 * @date 2023/5/4 15:01
 * @desc 提供一个 数据容器类 内部分别使用读锁保护数据的 read() 方法，写锁保护数据的 write() 方法。
 */
public class DataContainerStamped {
    private final StampedLock lock = new StampedLock();
    private int data;

    public DataContainerStamped(int data) {
        this.data = data;
    }
    public DataContainerStamped(){

    }

    public int read() throws InterruptedException {
        // 乐观锁 - 读锁
        long stamp = lock.tryOptimisticRead();
        System.out.println(Thread.currentThread().getName() + " optimistic read locking..." + stamp);
        Thread.sleep(2000);
        if (lock.validate(stamp)) {
            System.out.println(Thread.currentThread().getName() + " read finish..." + stamp + ", data:" + data);
            return data;
        }
        // 锁升级 - 读锁
        System.out.println(Thread.currentThread().getName() + " updating to read lock..." + stamp);
        try {
            stamp = lock.readLock();
            System.out.println(Thread.currentThread().getName() + " read lock " + stamp);
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + " read finish..." + stamp + ", data:" + data);
            return data;
        } finally {
            System.out.println(Thread.currentThread().getName() + " read unlock " + stamp);
            lock.unlockRead(stamp);
        }
    }

    public void write(int data) throws InterruptedException {
        long stamp = lock.writeLock();
        System.out.println(Thread.currentThread().getName() + " write lock " + stamp);
        try {
            Thread.sleep(2000);
            this.data = data;
        } finally {
            System.out.println(Thread.currentThread().getName() + " write unlock " + stamp);
            lock.unlockWrite(stamp);
        }
    }
}
